package com.example.tass.controller;

import cn.tass.SRJ1933.devices.inf.TassSignServerApi;
import cn.tass.SRJ1933.devices.params.response.sym.SymOperationMultiFinalResponse;
import cn.tass.SRJ1933.devices.params.response.sym.SymOperationMultiInitResponse;
import cn.tass.SRJ1933.devices.params.response.sym.SymOperationMultiUpdateResponse;
import cn.tass.SRJ1933.devices.params.response.sym.SymOperationResponse;
import cn.tass.exceptions.TAException;
import com.example.tass.common.ResultMessage;
import com.example.tass.domain.*;
import com.example.tass.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SymEncAndDecTest_3_5 {

    private static final Logger logger = LoggerFactory.getLogger(SymEncAndDecTest_3_5.class);
    private static String printFormat = "错误码[%d]\n错误消息[%s]\n接口结果： %s\n";

    // 初始化操作(连接上江南天安的SVSM服务器)
    private TassSignServerApi signServerApi;
    public SymEncAndDecTest_3_5(TassSignServerApi signServerApi) {
        this.signServerApi = signServerApi;
    }

    ///////////////////////// 【3.5】对称加解密 ///////////////////////////

    /**
     * 【3.5.1.1】对称加密 - 内部密钥
     *
     * @return 加密后的密文
     * @throws TAException
     */
    @GetMapping(value = "/symEncrypt")
    public ResultMessage symEncrypt(@RequestBody SymRequest symRequest) {
        try {
            String data = symRequest.getData();
            boolean isBase64 = StringUtils.isBase64(data);
            if (!isBase64) {
                data = StringUtils.stringToBase64String(data);
            }
            SymOperationResponse symOperationResponse = signServerApi.symEncrypt(symRequest.getKeyId(), symRequest.getKeyAccessCode(),
                    symRequest.getMode(), symRequest.getPadMode(), symRequest.getIv(), data);
            if (symOperationResponse.getCode() != 0) {
                logger.error(symOperationResponse.getMsg());
                return ResultMessage.newFailureResult(symOperationResponse.getMsg());
            } else {
                System.out.println("对称加密 - 内部密钥： " + String.format(printFormat, symOperationResponse.getCode(), symOperationResponse.getMsg(), symOperationResponse.getResult()));
                return ResultMessage.newSuccessResult(symOperationResponse.getResult());
            }
        } catch (TAException e) {
            logger.error(e.getMessage());
            return ResultMessage.newFailureResult(e.getMessage());
        }
    }


    /**
     * 【3.5.1.2】对称加密 - 外部密钥
     *
     * @param symRequestExtKey
     * @return
     */
    @GetMapping(value = "/symEncryptExtKey")
    public ResultMessage symEncrypt(@RequestBody SymRequestExtKey symRequestExtKey) {
        try {
            String data = symRequestExtKey.getData();
            boolean isBase64 = StringUtils.isBase64(data);
            if (!isBase64) {
                data = StringUtils.stringToBase64String(data);
            }
            SymOperationResponse symOperationResponse = signServerApi.symEncrypt(symRequestExtKey.getExtKeyInfo(), symRequestExtKey.getExtKeyInfoAlg(), symRequestExtKey.getEncKeyId(),
                    symRequestExtKey.getEnckeyAccessCode(), symRequestExtKey.getEncMode(), symRequestExtKey.getPadMode(), symRequestExtKey.getEncIv(),
                    symRequestExtKey.getMode(), symRequestExtKey.getPadMode(), symRequestExtKey.getIv(), data);
            if (symOperationResponse.getCode() != 0) {
                logger.error(symOperationResponse.getMsg());
                return ResultMessage.newFailureResult(symOperationResponse.getMsg());
            } else {
                System.out.println("对称加密 - 外部密钥： " + String.format(printFormat, symOperationResponse.getCode(), symOperationResponse.getMsg(), symOperationResponse.getResult()));
                return ResultMessage.newSuccessResult(symOperationResponse.getResult());
            }
        } catch (TAException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 【3.5.2.1】对称解密 - 内部密钥
     *
     * @param symRequest 解密请求数据
     * @return 解密后的原文信息
     */
    @GetMapping(value = "/symDecrypt")
    public ResultMessage symDecrypt(@RequestBody SymRequest symRequest) {
        try {
            SymOperationResponse symOperationResponse = signServerApi.symDecrypt(symRequest.getKeyId(), symRequest.getKeyAccessCode(),
                    symRequest.getMode(), symRequest.getPadMode(), symRequest.getIv(), symRequest.getData());
            if (symOperationResponse.getCode() != 0) {
                logger.error(symOperationResponse.getMsg());
                return ResultMessage.newFailureResult(symOperationResponse.getMsg());
            } else {
                System.out.println("对称解密 - 内部密钥： " + String.format(printFormat, symOperationResponse.getCode(), symOperationResponse.getMsg(), symOperationResponse.getResult()));
                String result = symOperationResponse.getResult();
                if(StringUtils.isBase64(result)){
                    return ResultMessage.newSuccessResult(result);
                }else {
                    return ResultMessage.newSuccessResult(StringUtils.Base64ToString(result));
                }
            }
        } catch (TAException e) {
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 【3.5.2.2】对称解密 - 外部密钥
     *
     * @param symRequestExtKey
     * @return
     */
    @GetMapping(value = "/symDecryptExtKey")
    public ResultMessage symDecrypt(@RequestBody SymRequestExtKey symRequestExtKey) {
        try {
            SymOperationResponse symOperationResponse = signServerApi.symDecrypt(symRequestExtKey.getExtKeyInfo(), symRequestExtKey.getExtKeyInfoAlg(), symRequestExtKey.getEncKeyId(),
                    symRequestExtKey.getEnckeyAccessCode(), symRequestExtKey.getEncMode(), symRequestExtKey.getPadMode(), symRequestExtKey.getEncIv(),
                    symRequestExtKey.getMode(), symRequestExtKey.getPadMode(), symRequestExtKey.getIv(), symRequestExtKey.getData());
            if (symOperationResponse.getCode() != 0) {
                logger.error(symOperationResponse.getMsg());
                return ResultMessage.newFailureResult(symOperationResponse.getMsg());
            } else {
                System.out.println("对称解密 - 外部密钥： " + String.format(printFormat, symOperationResponse.getCode(), symOperationResponse.getMsg(), symOperationResponse.getResult()));
                return ResultMessage.newSuccessResult(StringUtils.Base64ToString(symOperationResponse.getResult()));
            }
        } catch (TAException e) {
            throw new RuntimeException(e);
        }
    }


    ////////////////////// 3.5.3 数据多包加密（初始化）///////////////////////////////

    // 3.5.3.1 多包加密初始化（内部密钥）
    @GetMapping(value = "/symEncryptMultiInit")
    public ResultMessage symEncryptMultiInit(@RequestBody MyBaseSymRequest baseSymRequest) {

        try {
            SymOperationMultiInitResponse response = signServerApi.symEncryptMultiInit(baseSymRequest.getKeyId(),
                    baseSymRequest.getKeyAccessCode(), baseSymRequest.getMode(), baseSymRequest.getPadMode(), baseSymRequest.getIv());
            if (response.getCode() != 0) {
                logger.error(response.getMsg());
                return ResultMessage.newFailureResult(response.getMsg());
            } else {
                System.out.println("多包加密初始化（内部密钥）： " + String.format(printFormat, response.getCode(), response.getMsg(), response.getSymHandle()));
                return ResultMessage.newSuccessResult(response.getSymHandle());
            }
        } catch (TAException e) {
            throw new RuntimeException(e);
        }
    }

    // 3.5.3.2 多包加密初始化（外部密钥）
    @GetMapping(value = "/symEncryptMultiInitExtKey")
    public ResultMessage symEncryptMultiInitExtkey(@RequestBody MyBaseSymRequest request) {

        try {
            SymOperationMultiInitResponse response = signServerApi.symEncryptMultiInit(request.getExtKeyInfo(), request.getExtKeyInfoAlg(),
                    request.getEncKeyId(), request.getEnckeyAccessCode(), request.getEncMode(), request.getEncPadMode(), request.getEncIv(),
                    request.getMode(), request.getPadMode(), request.getIv());
            if (response.getCode() != 0) {
                logger.error(response.getMsg());
                return ResultMessage.newFailureResult(response.getMsg());
            } else {
                System.out.println("多包加密初始化（内部密钥）： " + String.format(printFormat, response.getCode(), response.getMsg(), response.getSymHandle()));
                return ResultMessage.newSuccessResult(response.getSymHandle());
            }
        } catch (TAException e) {
            throw new RuntimeException(e);
        }
    }

    // 3.5.4 数据多包加密（更新数据）
    @GetMapping(value = "/symEncryptMultiUpdate")
    public ResultMessage symEncryptMultiUpdate(@RequestBody MySymOperationMultiUpdateRequest request) {
        try {
            SymOperationMultiUpdateResponse response = signServerApi.symEncryptMultiUpdate(request.getSymHandle(), request.getData());
            if (response.getCode() != 0) {
                logger.error(response.getMsg());
                return ResultMessage.newFailureResult(response.getMsg());
            } else {
                System.out.println("数据多包加密（更新数据）： " + String.format(printFormat, response.getCode(), response.getMsg(), "加密会话句柄: " + response.getSymHandle() + ",迭代更新加密结果:" + response.getResult()));
                return ResultMessage.newSuccessResult(response.getSymHandle());
            }
        } catch (TAException e) {
            throw new RuntimeException(e);
        }
    }

    // 3.5.5数据多包加密（结束加密）
    @GetMapping(value = "/symEncryptMultiFinal")
    public ResultMessage symEncryptMultiFinal(@RequestBody MySymOperationMultiFinalRequest request) {
        try {
            SymOperationMultiFinalResponse response = signServerApi.symEncryptMultiFinal(request.getSymHandle());
            if (response.getCode() != 0) {
                logger.error(response.getMsg());
                return ResultMessage.newFailureResult(response.getMsg());
            } else {
                System.out.println("数据多包加密（结束加密）： " + String.format(printFormat, response.getCode(), response.getMsg(), response.getResult()));
                return ResultMessage.newSuccessResult(response.getResult());
            }
        } catch (TAException e) {
            throw new RuntimeException(e);
        }
    }


    // 3.5.6数据多包解密（初始化）
    //3.5.6.1多包解密初始化（内部密钥）
    @GetMapping(value = "/symDecryptMultiInit")
    public ResultMessage symDecryptMultiInit(@RequestBody MyBaseSymRequest request) {
        try {
            SymOperationMultiInitResponse response = signServerApi.symDecryptMultiInit(request.getKeyId(), request.getKeyAccessCode(),
                    request.getMode(), request.getPadMode(), request.getIv());
            if (response.getCode() != 0) {
                logger.error(response.getMsg());
                return ResultMessage.newFailureResult(response.getMsg());
            } else {
                System.out.println("多包解密初始化（内部密钥）： " + String.format(printFormat, response.getCode(), response.getMsg(), response.getSymHandle()));
                return ResultMessage.newSuccessResult(response.getSymHandle());
            }
        } catch (TAException e) {
            throw new RuntimeException(e);
        }
    }

    // 3.5.6.2 多包解密初始化（外部密钥）
    @GetMapping(value = "/symDecryptMultiInitExtKey")
    public ResultMessage symDecryptMultiInitExtKey(@RequestBody MyBaseSymRequest request) {
        try {
            SymOperationMultiInitResponse response = signServerApi.symDecryptMultiInit(request.getExtKeyInfo(), request.getExtKeyInfoAlg(), request.getEncKeyId(), request.getEnckeyAccessCode(),
                    request.getEncMode(), request.getEncPadMode(), request.getEncIv(), request.getMode(), request.getPadMode(), request.getIv());
            if (response.getCode() != 0) {
                logger.error(response.getMsg());
                return ResultMessage.newFailureResult(response.getMsg());
            } else {
                System.out.println(" 多包解密初始化（外部密钥）： " + String.format(printFormat, response.getCode(), response.getMsg(), response.getSymHandle()));
                return ResultMessage.newSuccessResult(response.getSymHandle());
            }
        } catch (TAException e) {
            throw new RuntimeException(e);
        }

    }

    // 3.5.7数据多包解密（更新数据）
    @GetMapping(value = "/symDecryptMultiUpdate")
    public ResultMessage symDecryptMultiUpdate(@RequestBody MySymOperationMultiUpdateRequest request) {
        try {
            SymOperationMultiUpdateResponse response = signServerApi.symDecryptMultiUpdate(request.getSymHandle(), request.getData());
            if (response.getCode() != 0) {
                logger.error(response.getMsg());
                return ResultMessage.newFailureResult(response.getMsg());
            } else {
                System.out.println("数据多包解密（更新数据）： " + String.format(printFormat, response.getCode(), response.getMsg(), "解密会话句柄: " + response.getSymHandle() + ",解密数据结果:" + response.getResult()));
                return ResultMessage.newSuccessResult(response.getSymHandle());
            }
        } catch (TAException e) {
            throw new RuntimeException(e);
        }
    }

    // 3.5.8 数据多包解密（结束解密）
    @GetMapping(value = "/symDecryptMultiFinal")
    public ResultMessage symDecryptMultiFinal(@RequestBody MySymOperationMultiFinalRequest request) {
        try {
            SymOperationMultiFinalResponse response = signServerApi.symDecryptMultiFinal(request.getSymHandle());
            if (response.getCode() != 0) {
                logger.error(response.getMsg());
                return ResultMessage.newFailureResult(response.getMsg());
            } else {
                System.out.println("数据多包解密（结束解密）： " + String.format(printFormat, response.getCode(), response.getMsg(), response.getResult()));
                return ResultMessage.newSuccessResult(response.getResult());
            }
        } catch (TAException e) {
            throw new RuntimeException(e);
        }
    }
}
